package com.ctshk.rpc.finance.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.dto.Result;
import com.ctshk.common.enums.*;
import com.ctshk.common.exception.BusinessException;
import com.ctshk.common.model.PageResponse;
import com.ctshk.common.model.TokenUser;
import com.ctshk.common.utils.EntityUtil;
import com.ctshk.common.utils.SnowflakeIdWorker;
import com.ctshk.rpc.finance.dto.advance.AdvancePaymentApplyDTO;
import com.ctshk.rpc.finance.dto.advance.AdvancePaymentApplyListDTO;
import com.ctshk.rpc.finance.entity.FinanceAdvancePayment;
import com.ctshk.rpc.finance.entity.FinanceAdvancePaymentApply;
import com.ctshk.rpc.finance.entity.FinanceAdvancePaymentApplySummary;
import com.ctshk.rpc.finance.json.FileJson;
import com.ctshk.rpc.finance.mapper.FinanceAdvancePaymentApplyMapper;
import com.ctshk.rpc.finance.mapper.FinanceAdvancePaymentApplySummaryMapper;
import com.ctshk.rpc.finance.mapper.FinanceAdvancePaymentMapper;
import com.ctshk.rpc.finance.mapper.FinanceAdvancePaymentRefundMapper;
import com.ctshk.rpc.finance.req.advance.AdvancePaymentApplyAddReq;
import com.ctshk.rpc.finance.req.advance.AdvancePaymentApplyIdReq;
import com.ctshk.rpc.finance.req.advance.AdvancePaymentApplyListReq;
import com.ctshk.rpc.finance.req.advance.AdvancePaymentApprovalReq;
import com.ctshk.rpc.finance.req.bill.RollBackReq;
import com.ctshk.rpc.finance.service.IFinanceAdvancePaymentApplyService;
import com.ctshk.rpc.system.dto.UserDTO;
import com.ctshk.rpc.system.service.ISysUserService;
import com.ctshk.rpc.workflow.dto.ApprovalCheckDTO;
import com.ctshk.rpc.workflow.dto.ApprovalStartDTO;
import com.ctshk.rpc.workflow.service.ISysApprovalService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;

/**
 * <p>
 * 财务预收款申请表 服务实现类
 * </p>
 *
 * @author 叶冠峰
 * @since 2021-03-26
 */
@Slf4j
@DubboService
public class FinanceAdvancePaymentApplyServiceImpl extends ServiceImpl<FinanceAdvancePaymentApplyMapper, FinanceAdvancePaymentApply> implements IFinanceAdvancePaymentApplyService {

    @Autowired
    private FinanceAdvancePaymentApplyMapper advancePaymentApplyMapper;
    @Autowired
    private FinanceAdvancePaymentMapper advancePaymentMapper;
    @Autowired
    private FinanceAdvancePaymentApplySummaryMapper advancePaymentApplySummaryMapper;
    @Autowired
    private FinanceAdvancePaymentRefundMapper financeAdvancePaymentRefundMapper;

    @DubboReference
    private ISysApprovalService sysApprovalService;
    @DubboReference
    private ISysUserService sysUserService;

    /*@Autowired
    private RedisTemplate<String, Object> redisTemplate;*/


    /**
     * 列表
     *
     * @param req
     * @param currentUser
     * @return
     */
    @Override
    public Result<PageResponse<AdvancePaymentApplyListDTO>> list(AdvancePaymentApplyListReq req, TokenUser currentUser) {
        Page<FinanceAdvancePaymentApply> page = new Page<>(req.getPageNo(), req.getPageSize());
        QueryWrapper<FinanceAdvancePaymentApply> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("advance_payment_id",req.getPaymentId());
        queryWrapper.eq("is_deleted",0);
        queryWrapper.orderByDesc("gmt_create");
        Page<FinanceAdvancePaymentApply> applyPage = advancePaymentApplyMapper.selectPage(page, queryWrapper);
        if (CollectionUtils.isEmpty(applyPage.getRecords())) {
            return Result.success(PageResponse.empty(applyPage.getCurrent()));
        }
        List<AdvancePaymentApplyListDTO> list = new ArrayList<>();
        applyPage.getRecords().forEach(item -> {
            AdvancePaymentApplyListDTO dto = EntityUtil.copy(item,AdvancePaymentApplyListDTO.class);
            //申请人
        //    UserDTO userDto = (UserDTO) redisTemplate.opsForValue().get(RedisConstants.ACCOUNT_QUERY_KEY + item.getCreateId());
            UserDTO userDto = sysUserService.queryCacheUser(item.getCreateId());
            if (userDto != null){
                dto.setApplier(userDto.getFullName());
                dto.setDeptName(userDto.getDept());
            }
            list.add(dto);
        });
        PageResponse<AdvancePaymentApplyListDTO> result = new PageResponse<>(list,
                applyPage.getCurrent() == 1,
                applyPage.getTotal() <= (applyPage.getCurrent() * applyPage.getSize()),
                applyPage.getTotal(),
                applyPage.getCurrent(),
                applyPage.getSize());
        return Result.success(result);
    }

    /**
     * 申请
     *
     * @param req
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result add(AdvancePaymentApplyAddReq req) {
        QueryWrapper<FinanceAdvancePayment> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("supplier_id",req.getSupplierId());
        FinanceAdvancePayment payment = advancePaymentMapper.selectOne(queryWrapper);
        if (payment == null){
            //未记录
            payment = EntityUtil.copy(req, FinanceAdvancePayment.class);
            payment.setId(SnowflakeIdWorker.nextId());
            payment.setCreateId(req.getUserId());
            payment.setGmtCreate(LocalDateTime.now());
            payment.setIsDeleted(0);
            int insert = advancePaymentMapper.insert(payment);
            if (insert <= 0){
                throw new BusinessException(SystemError.SYS_437);
            }
        }
        //新增申请记录
        FinanceAdvancePaymentApply paymentApply = EntityUtil.copy(req, FinanceAdvancePaymentApply.class);
        paymentApply.setId(SnowflakeIdWorker.nextId());
        paymentApply.setAdvancePaymentId(payment.getId());
        List<FileJson> fileJson = req.getFileJson();
        paymentApply.setFileJson(JSON.toJSONString(fileJson));
        paymentApply.setCreateId(req.getUserId());
        paymentApply.setApprovalStatus(2);
        paymentApply.setGmtCreate(LocalDateTime.now());
        paymentApply.setIsDeleted(0);
        boolean save = save(paymentApply);
        if (!save){
            throw new BusinessException(SystemError.SYS_437);
        }
        //发起审批
        Long approvalId = startApproval(paymentApply.getId(), paymentApply.getId(), req.getUserId());
        paymentApply.setApprovalId(approvalId);
        boolean update = updateById(paymentApply);
        if (!update){
            throw new BusinessException(SystemError.SYS_437);
        }
        return Result.success(paymentApply.getId());
    }

    /**
     * 详情
     *
     * @param req
     * @return
     */
    @Override
    public Result<AdvancePaymentApplyDTO> detail(AdvancePaymentApplyIdReq req) {
        //申请预收款详情
        AdvancePaymentApplyDTO dto =  advancePaymentApplyMapper.queryDetail(req.getApplyId());
        if (dto == null){
            throw new BusinessException(SystemError.FINANCE_ADVANCE_17006);
        }
        //获取申请人
//        UserDTO userDto = (UserDTO) redisTemplate.opsForValue().get(RedisConstants.ACCOUNT_QUERY_KEY + dto.getCreateId());
        UserDTO userDto = sysUserService.queryCacheUser(dto.getCreateId());

        if (userDto != null){
            dto.setApplier(userDto.getDept());
            dto.setDeptName(userDto.getCnName());
        }
        //附件
        if (StringUtils.isNotBlank(dto.getFileJson())){
            List<FileJson> fileJsonList = JSON.parseArray(dto.getFileJson(), FileJson.class);
            dto.setFileJsonList(fileJsonList);
        }
        return Result.success(dto);
    }

    /**
     * 审批
     *
     * @param req
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result approval(AdvancePaymentApprovalReq req) {
        QueryWrapper<FinanceAdvancePaymentApply> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.eq("approval_id",req.getApprovalId());
        queryWrapper1.eq("is_deleted",0);
        FinanceAdvancePaymentApply apply = advancePaymentApplyMapper.selectOne(queryWrapper1);
        if (apply == null){
            throw new BusinessException(SystemError.FINANCE_ADVANCE_17006);
        }
        //审批中状态才能操作审批
        if (!Objects.equals(apply.getApprovalStatus(),2)){
            throw new BusinessException(SystemError.FINANCE_ADVANCE_17007);
        }
        apply.setApprovalStatus(req.getType());
        apply.setModifiedId(req.getUserId());
        boolean bl = updateById(apply);
        if (!bl){
            throw new BusinessException(SystemError.SYS_437);
        }
        Result<ApprovalCheckDTO> check = sysApprovalService.check(req.getApprovalId(), req.getUserId(), req.getType(), req.getComments());
        if (check == null || !check.getData().getIsFinish()){
            throw new BusinessException(SystemError.SYS_437);
        }
        if (Objects.equals(req.getType(),3)){
            //审批通过
            QueryWrapper<FinanceAdvancePayment> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("supplier_id",apply.getSupplierId());
            queryWrapper.eq("is_deleted",0);
            FinanceAdvancePayment payment = advancePaymentMapper.selectOne(queryWrapper);
            if (payment == null){
                throw new BusinessException(SystemError.FINANCE_ADVANCE_17002);
            }
            //更新汇总
            QueryWrapper<FinanceAdvancePaymentApplySummary> summaryQueryWrapper = new QueryWrapper<>();
            summaryQueryWrapper.eq("advance_payment_id",payment.getId());
            summaryQueryWrapper.eq("supplier_id",payment.getSupplierId());
            summaryQueryWrapper.eq("currency_id",apply.getCurrencyId());
            summaryQueryWrapper.eq("is_deleted",0);
            FinanceAdvancePaymentApplySummary summary = advancePaymentApplySummaryMapper.selectOne(summaryQueryWrapper);
            if (summary == null){
                //新增币种统计
                summary = new FinanceAdvancePaymentApplySummary();
                summary.setId(SnowflakeIdWorker.nextId());
                summary.setAdvancePaymentId(payment.getId());
                summary.setSupplierId(payment.getSupplierId());
                summary.setCurrencyId(apply.getCurrencyId());
                summary.setAmountUsed(BigDecimal.ZERO);
                summary.setCurrency(apply.getCurrency());
                summary.setExchangeRate(apply.getExchangeRate());
                summary.setMoneyAmount(apply.getMoneyAmount());
                summary.setUnavailableAmount(apply.getUnavailableAmount());
                summary.setAvailableAmount(apply.getMoneyAmount().subtract(apply.getUnavailableAmount()));
                summary.setRemainingAmount(summary.getAvailableAmount());
                summary.setCreateId(req.getUserId());
                summary.setGmtCreate(LocalDateTime.now());
                summary.setIsDeleted(0);
                int insert = advancePaymentApplySummaryMapper.insert(summary);
                if (insert <= 0){
                    throw new BusinessException(SystemError.SYS_437);
                }
            }else{
                //更新
                summary.setMoneyAmount(summary.getMoneyAmount().add(apply.getMoneyAmount()));
                summary.setUnavailableAmount(summary.getUnavailableAmount().add(apply.getUnavailableAmount()));
                summary.setAvailableAmount(summary.getAvailableAmount().add(apply.getAvailableAmount()));
                summary.setRemainingAmount(summary.getRemainingAmount().add(apply.getAvailableAmount()));
                summary.setModifiedId(req.getUserId());
                int update = advancePaymentApplySummaryMapper.updateById(summary);
                if (update <= 0){
                    throw new BusinessException(SystemError.SYS_437);
                }
            }
        }
        return Result.success(apply.getId());
    }

    /**
     * 撤回审批
     *
     * @param req
     * @return
     */
    @Override
    public Result rollBack(RollBackReq req) {
        QueryWrapper<FinanceAdvancePaymentApply> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.eq("approval_id",req.getApprovalId());
        queryWrapper1.eq("is_deleted",0);
        FinanceAdvancePaymentApply apply = advancePaymentApplyMapper.selectOne(queryWrapper1);
        if (apply == null){
            throw new BusinessException(SystemError.FINANCE_ADVANCE_17006);
        }
        if (!Objects.equals(apply.getCreateId(),req.getUserId())){
            throw new BusinessException(SystemError.FINANCE_ERROR_17039);
        }
        //删除申请记录
        apply.setIsDeleted(1);
        apply.setModifiedId(req.getUserId());
        int del = advancePaymentApplyMapper.updateById(apply);
        if (del <= 0){
            throw new BusinessException(SystemError.SYS_437);
        }
        return Result.success();
    }


    /**
     * 发起审批流程
     * @param id
     * @param businessId
     * @param userId
     */
    private Long startApproval(Long id, Long businessId, Long userId) {
        Map<String, Object> extendParams = new HashMap<>();
        extendParams.put("id", id);
        try{
            Result<ApprovalStartDTO> approvalResult = sysApprovalService.start(SystemBusinessType.FINANCE.getCode(),
                    SysApprovalType.PAYMENT_FINANCE.getCode(), businessId,
                    userId, null, JSON.toJSONString(extendParams));
            if (!approvalResult.isSuccess()) {
                throw new BusinessException(SystemError.CUSTOM_ORDER_4044);
            }
            return approvalResult.getData().getApprovalId();
        }catch (Exception e){
            throw new BusinessException(SystemError.SYS_422);
        }
    }

}
